
#include <string.h>

#include "SefonIotPlatform.h"
#include "SefonIotNet.h"
#include "SefonIotLog.h"
#include "SefonIotHexdump.h"


/*** TCP connection ***/
int ReadTcp(sfiot_network_pt pNetwork, char *buffer, uint32_t len, uint32_t timeout_ms)
{
    return TcpRead(pNetwork->handle, buffer, len, timeout_ms);
}


static int WriteTcp(sfiot_network_pt pNetwork, const char *buffer, uint32_t len, uint32_t timeout_ms)
{
    return TcpWrite(pNetwork->handle, buffer, len, timeout_ms);
}

static int DisconnectTcp(sfiot_network_pt pNetwork)
{
    if ( 0 == pNetwork->handle) {
        return -1;
    }

    TcpDestroy(pNetwork->handle);
    pNetwork->handle = 0;
    return 0;
}


static int ConnectTcp(sfiot_network_pt pNetwork)
{
    if (NULL == pNetwork) {
        SFIOT_LOG_ERROR("network is null");
        return 1;
    }

    pNetwork->handle = TcpEstablish(pNetwork->pHostAddress, pNetwork->port);
    if ( 0 == pNetwork->handle ) {
        return -1;
    }

    return 0;
}


/*** SSL connection ***/
//???????ssl
static int ReadSsl(sfiot_network_pt pNetwork, char *buffer, uint32_t len, uint32_t timeout_ms)
{
    if (NULL == pNetwork) {
        SFIOT_LOG_ERROR("network is null");
        return -1;
    }
    return -1;
    //return sfiot_platform_ssl_read((void *)pNetwork->handle, buffer, len, timeout_ms);
}

static int WriteSsl(sfiot_network_pt pNetwork, const char *buffer, uint32_t len, uint32_t timeout_ms)
{
    if (NULL == pNetwork) {
        SFIOT_LOG_ERROR("network is null");
        return -1;
    }
    return -1;
    //return sfiot_platform_ssl_write((void *)pNetwork->handle, buffer, len, timeout_ms);
}

static int DisconnectSsl(sfiot_network_pt pNetwork)
{
    if (NULL == pNetwork) {
        SFIOT_LOG_ERROR("network is null");
        return -1;
    }

    //sfiot_platform_ssl_destroy((void *)pNetwork->handle);
    //pNetwork->handle = 0;

    return 0;
}

static int ConnectSsl(sfiot_network_pt pNetwork)
{
    if (NULL == pNetwork) {
        SFIOT_LOG_ERROR("network is null");
        return 1;
    }
    /*
    if (0 != (pNetwork->handle = (intptr_t)sfiot_platform_ssl_establish(
                                            pNetwork->pHostAddress,
                                            pNetwork->port,
                                            pNetwork->ca_crt,
                                            pNetwork->ca_crt_len + 1))) {
        return 0;
    } else {
        //TODO SHOLUD not remove this handle space
        // The space will be freed by calling disconnect_ssl()
        //sfiot_memory_free((void *)pNetwork->handle);
        return -1;
    }
    */
    return -1;
}



/****** network interface ******/
//???????ssl

int SFIotNetRead(sfiot_network_pt pNetwork, char *buffer, uint32_t len, uint32_t timeout_ms)
{
    if (NULL == pNetwork->ca_crt) { //TCP connection
        return ReadTcp(pNetwork, buffer, len, timeout_ms);
    } else { //SSL connection
        return ReadSsl(pNetwork, buffer, len, timeout_ms);
    }
}


int SFIotNetWrite(sfiot_network_pt pNetwork, const char *buffer, uint32_t len, uint32_t timeout_ms)
{
    if (NULL == pNetwork->ca_crt) { //TCP connection
        return WriteTcp(pNetwork, buffer, len, timeout_ms);
    } else { //SSL connection
        return WriteSsl(pNetwork, buffer, len, timeout_ms);
    }
}


int SFIotNetDisconnect(sfiot_network_pt pNetwork)
{
    if (NULL == pNetwork->ca_crt) { //TCP connection
        return DisconnectTcp(pNetwork);
    } else { //SSL connection
        return DisconnectSsl(pNetwork);
    }
}


int SFIotNetConnect(sfiot_network_pt pNetwork)
{
    if (NULL == pNetwork->ca_crt) { //TCP connection
        return ConnectTcp(pNetwork);
    } else { //SSL connection
        return ConnectSsl(pNetwork);
    }
}


int SFIotNetInit(sfiot_network_pt pNetwork, const char *host, uint16_t port, const char *ca_crt)
{
    pNetwork->pHostAddress = host;
    pNetwork->port = port;
    pNetwork->ca_crt = ca_crt;
    if (NULL == ca_crt) {
        pNetwork->ca_crt_len = 0;
    } else {
        pNetwork->ca_crt_len = strlen(ca_crt);
    }

    pNetwork->handle = 0;
    pNetwork->read = SFIotNetRead;
    pNetwork->write = SFIotNetWrite;
    pNetwork->disconnect = SFIotNetDisconnect;
    pNetwork->connect = SFIotNetConnect;

    return 0;
}
